#pragma once
#ifndef MYLOGGER_HPP
#define MYLOGGER_HPP
#include "Configuration.hpp"
#include <iostream>
#include <log4cpp/Category.hh>
#include <log4cpp/PropertyConfigurator.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/RollingFileAppender.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/OstreamAppender.hh>
#include <string>
#include <memory>
using namespace std;
using namespace log4cpp;
namespace jpx{
//操纵类型枚举
enum class OperationType
{
    USER_REGISTER = 1, //用户注册
    USER_LOGIN,        //用户登录
    VIEW_CAMERA_INFO   //查看摄像头信息
};
class MyLogger
{
public:
    //获取单例实例
    static MyLogger & get_instance();
    //初始化日志系统
    bool initialize_logger(const string & configFile = "");
private:
    bool initialize(const string & configFile = "",const string & configure = "");
public:
    //记录用户操作
    void log_user_operation_by_user(OperationType opType,
                            const string & userId,
                            const string & email = "",
                            const string & additionalInfo = "",
                            const string & ipAddress = "");

    //记录用户注册操作
    void log_user_register_by_user(const string & userId,
                           const string & username,
                           const string & email = "",
                           const string & additionalInfo = "",
                           const string & ipAddress = "");
    //记录用户登录操作
    void log_user_login_by_user(const string & userId,
                        const string & username,
                        const string & ipAddress = "",
                        const string & userAgent = "");
    void log_view_cameraInfo_by_user(const string & userId,
                             const string & username,
                             const string & cameraID,
                             const string & cameraName = "",
                             const string & ipAddress = "");

    //获取操作类型字符串
    string get_operation_typeString(OperationType onType);

    //记录调试信息
    void log_debug(const string & message,
                   const string & location = "",
                   int lineNumber = 0,
                   const string & additionalInfo = "");

    //记录警告信息
    void log_warn(const string & message,
                  const string & location = "",
                  int lineNumber = 0,
                  const string & additionalInfo = "");

    //记录错误信息
    void log_error(const string & message,
                   const string & location = "",
                   int lineNumber = 0,
                   const string & additionalInfo = "");

    //记录信息
    void log_info(const string & message,
                  const string & location = "",
                   int lineNumber = 0,
                  const string & additionalInfo = "");
    //关闭日志系统
    void shutdown();
private:
    MyLogger() = default;
    ~MyLogger();
    //禁止拷贝和赋值
    MyLogger(const MyLogger & ) = delete;
    MyLogger & operator=(const MyLogger &) = delete;

    //使用配置文件初始化
    bool initialize_with_config(const string & configfile);

    //使用代码配置初始化
    bool initialize_with_defaultConfig();

    log4cpp::Category * _logger;
    //用户专用的日志映射器
    unordered_map<string, log4cpp::Category*> _userLoggers;
    mutex _userLoggersMutex;
    //获取或创建用户专用的日志器
    log4cpp::Category * get_or_create_user_logger(const string & userId);
    log4cpp::Category * _debugLogger;
    log4cpp::Category * _infoLogger;
    log4cpp::Category * _warnLogger;
    log4cpp::Category * _errorLogger;
    bool _initialized = false;
};
}//end of namespace jpx

#define LOG_DEBUG(message) \
        jpx::MyLogger::get_instance().log_debug(message, __FUNCTION__, __LINE__)

#define LOG_INFO(message) \
        jpx::MyLogger::get_instance().log_info(message, __FUNCTION__, __LINE__)

#define LOG_WARN(message) \
        jpx::MyLogger::get_instance().log_warn(message, __FUNCTION__, __LINE__)

#define LOG_ERROR(message) \
        jpx::MyLogger::get_instance().log_error(message, __FUNCTION__, __LINE__)

#define LOG_DEBUG_EX(message, additionalInfo) \
        jpx::MyLogger::get_instance().log_debug(message, __FUNCTION__, __LINE__, additionalInfo)

#define LOG_INFO_EX(message, additionalInfo) \
        jpx::MyLogger::get_instance().log_info(message, __FUNCTION__, __LINE__, additionalInfo)

#define LOG_WARN_EX(message, additionalInfo) \
        jpx::MyLogger::get_instance().log_warn(message, __FUNCTION__, __LINE__, additionalInfo)

#define LOG_ERROR_EX(message, additionalInfo) \
        jpx::MyLogger::get_instance().log_error(message, __FUNCTION__, __LINE__, additionalInfo)

#define LOG_USER_REGISTER(userId, username, email, additionalInfo, ipAddress) \
        jpx::MyLogger::get_instance().log_user_register_by_user(userId, username, email, additionalInfo, ipAddress)

#define LOG_USER_LOGIN(userId, username, ipAddress, userAgent) \
        jpx::MyLogger::get_instance().log_user_login_by_user(userId, username, ipAddress, userAgent)

#define LOG_VIEW_CAMERA_INFO(userId, username, cameraId, cameraName, ipAddress) \
        jpx::MyLogger::get_instance().log_view_cameraInfo_by_user(userId, username, cameraId, cameraName, ipAddress)
#endif //MYLOGGER_HPP

